/*
 * $Id: VelocityTemplate.java,v 1.5 2003/05/26 20:47:14 znamenacek Exp $
 *
 * Copyright (c) Milan Jedlicka
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

package net.sf.vofce.export;

import net.sf.vofce.project.Config;
import net.sf.vofce.project.Project;
import net.sf.vofce.guts.Function;

import org.apache.log4j.Category;

import java.io.*;
import java.util.Vector;
import java.util.Properties;
import java.awt.Color;

import org.apache.velocity.VelocityContext;
import org.apache.velocity.Template;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.MethodInvocationException;

/**
 * Velocity template for exporting to text formats.
 * 
 * @author Milan Jedlicka
 */
public class VelocityTemplate implements net.sf.vofce.export.Template {

	/** Logger instance. */
	protected static Category logger = Category.getRoot();

// Avaible data for templates

	/** Instance of the configuration system. */
	protected static Config config = Config.getInstance();
	
	/** Project instance. */
	protected Project project = Project.getInstance();

	/** Image Exporter instance */
	protected ImageExporter ie;
	
	/** Parse <code>String</code> for better parse of author, extension, ...*/
	public static final int DONT_PARSE = 0;

	/** Don't parse <code>String</code> */
	public static final int PARSE = 1;
	
// Available tags

	/** Author tag */
	public static final String AUTHOR_TAG = "author";

	/** Extension tag */
	public static final String EXTENSION_TAG = "extension";

	/** Version tag */
	public static final String VERSION_TAG = "version";

	/** File where is the template saved */
	File templateFile;
	
	/** Type of template (internal, preddefined, user)*/
	int templateType;
	
	String templateName;
	
	String comment;
	String description;
	String author;
	String version;
	String extension;
	
	Template template;
	
	/**
	 * Default constructor
	 * @param templateFileName 	name of template
	 */
	public VelocityTemplate(File templateFile, int type) throws Exception, ResourceNotFoundException, ParseErrorException { 
		
		this.templateFile = templateFile;
		templateName = templateFile.getName().substring(0, templateFile.getName().indexOf(".vm"));
		this.templateType = type;

		
		// Template init
	
		VelocityEngine ve = new VelocityEngine();

		ve.setProperty( VelocityEngine.RUNTIME_LOG_LOGSYSTEM, this);
		
		String sep = System.getProperty("file.separator");
		
		Properties p = new Properties();
		p.setProperty("file.resource.loader.path", templateFile.getParent());
		ve.init(p);
			
		template = null;
		template = ve.getTemplate(templateFile.getName());

		// Template info
		comment = getWholeComment(PARSE);	
		
		description = comment.substring(0, comment.indexOf("\n"));	

		if (comment.indexOf(EXTENSION_TAG) != -1) {
			extension = comment.substring(comment.indexOf(EXTENSION_TAG) + EXTENSION_TAG.length() + 1,                                                 comment.indexOf("\n", comment.indexOf(EXTENSION_TAG)));
                } else {
        		extension = "<undefined>";
	        }
	
		if (comment.indexOf(AUTHOR_TAG) != -1) {
			author = comment.substring(comment.indexOf(AUTHOR_TAG) + AUTHOR_TAG.length() + 1, 
						 comment.indexOf("\n", comment.indexOf(AUTHOR_TAG))); 
		} else {
			author = "<none>";
		}
	
		if (comment.indexOf(VERSION_TAG) != -1) {
			version = comment.substring(comment.indexOf(VERSION_TAG) + VERSION_TAG.length() + 1, 
					 comment.indexOf("\n", comment.indexOf(VERSION_TAG))); 
		} else {
			version = "<undefined>";		
		}
		
	}

// Implements export.Template methods
	public String getName() {
		return templateName;
	}

	public String getDescription() {
		return description;
	}

	public String getExtension() {
		return extension;
	}
	
	public String getAuthor() {
		return author;
	}
	
	public String getVersion() {
		return version;
	}

	public void exportTo(File file) {
		try {
			VelocityContext context = new VelocityContext();

			// Prepare funciton list for template
			Function[] functions = project.getFunctions();

			ExportColor[] colors = new ExportColor[project.getSize()];
			for (int i = 0; i < project.getSize(); i++) {
				colors[i] = new ExportColor(config.getFunctionColor(i));
			}

			
			// Data for templates
			context.put("functions", functions);
			context.put("colors", colors);
			context.put("graphs", ie);
			context.put("path", file.getParent());
			context.put("filename", file.getName());

			String filename = file.getName();
			int extPresent = filename.indexOf("." + getExtension());
			if (extPresent != -1) {
				filename = filename.substring(0, extPresent);
				context.put("fileprefix", filename);
			} else {
				context.put("fileprefix", filename);
			}
			
			// Export to template
	
	
			BufferedWriter writer = writer = new BufferedWriter(
				new OutputStreamWriter(new FileOutputStream(file)));
			if (template != null) {
				template.merge(context, writer);
			}
	
			writer.flush();
			writer.close();

			
		} catch(Exception e) {
			logger.error(e);
		}
	}
	
	public void setImgExporter(ImageExporter ie) {
		this.ie = ie;
	}

//---------------------------
	
	/**
	 * Sets to template field of <code>Functions</code>
	 */
	public void setFunctions(/* Pole funkci */) {
	}
	
	/**
	 * @return 	the <code>String</code> destribing template
	 */
	public String getWholeComment(int parse) {
		
		String comment = "";
		
		BufferedReader stream = null;
		try {
			String sep = System.getProperty("file.separator");
			stream = new BufferedReader(new FileReader(templateFile.getParent() + sep + templateFile.getName()));
		} catch(FileNotFoundException e) {
			logger.error("VelocityTemplate: Template file not found.");
		}
	
		if (stream != null) {
			String strLine = "";
			
			int beginTagPos = -1;
			int endTagPos = -1;
			
			// Catch begin of comment --- #**
			do {
				try {
					strLine = stream.readLine();
					beginTagPos = strLine.indexOf("#**"); 
				} catch(IOException e) {
					e.printStackTrace();
				}
				
			} while (beginTagPos == -1); 
	
			// Catch end of comment -- *#
			endTagPos = strLine.indexOf("*#");

			if (endTagPos == -1) {
				comment += strLine.substring(beginTagPos + 3, strLine.length());
				
				do {
					try {
						strLine = stream.readLine();
						endTagPos = strLine.indexOf("*#");		
						if (endTagPos == -1) { comment += strLine; }
					} catch(IOException e) {			
						e.printStackTrace();
					}
				} while(endTagPos == -1);
				
				comment += strLine.substring(0, endTagPos);
				
			} else {
				comment += strLine.substring(beginTagPos + 3, endTagPos);	
			}
			
		}

		if (parse == PARSE) {
			return parseComment(comment);
		} else {
			return comment;
		}
	}

	/**
	 * @return 	the parsed <code>String</code> 
	 */
	public String parseComment(String commentIn) {
		String commentOut = "";
		int lastAtPos = -1;
		int atPos;
		
		atPos = commentIn.indexOf("@");
		
		if (atPos != -1) {
			while (atPos != -1) {
				commentOut += commentIn.substring(lastAtPos + 1, atPos) + "\n";	
				lastAtPos = atPos;
				atPos = commentIn.indexOf("@", lastAtPos + 1);
			}
			commentOut += commentIn.substring(lastAtPos + 1, commentIn.length()) + "\n";
			return commentOut;
		} else { 
			return commentIn;
		}
	}
	
	public String toString() {
		String sep = System.getProperty("file.separator");
		return templateName;
	}

	public int getType() {

		return templateType;
	}
}
